Pony vs O-CPS
$ cat main.pony
use "time"
actor Main
fun factorial(x: I64): I64 =>
if x == 0 then
1
else
x * factorial(x - 1)
end
fun ack(m: I64, n: I64): I64 =>
if m == 0 then
n + 1
else if n == 0 then
ack(m - 1, 1)
else
ack(m - 1, ack(m, n - 1))
end end
new create(env: Env) =>
let axs: U64 = Time.nanos()
let a: I64 = ack(3,4)
let axe: U64 = Time.nanos()
let fs: U64 = Time.nanos()
let f: I64 = factorial(5)
let fe: U64 = Time.nanos()
let fac: U64 = fe - fs
let akk: U64 = axe - axs
env.out.print("Ackerman: " + fac.string() + "ns, " + a.string())
env.out.print("Factorial: " +akk.string() + "ns, " + f.string())
$ ponyc
$ ./voxoz
Ackerman: 80332ns, 125
Factorial: 291ns, 120
В то время как у нас:
#[bench]
fn fac_rec<'a>(b: &'a mut Bencher) {
let h = handle::new(Interpreter::new().unwrap());
let eval = &"fac:{$[x=1;1;x*fac[x-1]]}".to_string();
let mut code = h.borrow_mut().parse(eval);
h.borrow_mut().run(code).unwrap();
let f = h.borrow_mut().parse(&"fac[5]".to_string());
b.iter(|| {
h.borrow_mut().run(f);
h.borrow_mut().gc();
})
}
#[bench]
fn akkerman_k<'a>(b: &'a mut Bencher) {
let h = handle::new(Interpreter::new().unwrap());
h.borrow_mut().define_primitives();
let akk =
h.borrow_mut().parse(&"f:{[x;y]$[0=x;1+y;$[0=y;f[x-1;1];f[x-1;f[x;y-1]]]]}".to_s
tring());
h.borrow_mut().run(akk).unwrap();
let call = h.borrow_mut().parse(&"f[3;4]".to_string());
b.iter(|| {
h.borrow_mut().run(call);
h.borrow_mut().gc();
})
}
test akkerman_k ... bench: 442 ns/iter (+/- 37)
test fac_rec ... bench: 195 ns/iter (+/- 55)